public class CloneSPCtlEx {

    public class ChkEnt {
        public boolean selected { set; get; }
        public Entitlement__c e { get; set; }
        public ChkEnt(Entitlement__c e) {
            this.e = e;
            this.selected = true;
        }
    }
    public List<ChkEnt> chkEntitlements { get; set; }
    
    public Boolean getZeroEntitlements() { return (chkEntitlements.size()==0); }

    ApexPages.StandardController sc;
    Support_Program__c sp;
    public CloneSPCtlEx(ApexPages.StandardController sc) {
       this.sc = sc;
       sp = (Support_Program__c)sc.getRecord();
       Entitlement__c[] eArr = [Select Id,Name,Start_Date__c,End_Date__c,Support_Program__c,Business_Hours__c,IsDefault__c,
           Cases_Remaining__c,Case_Pack__c,Renewal_Amount__c From Entitlement__c Where Support_Program__c=:sp.Id];
       chkEntitlements = new List<ChkEnt>();
       for(Entitlement__c e:eArr) {
           ChkEnt ce = new ChkEnt(e);
           chkEntitlements.add(ce);
       }
    }
    
    public class InvalidInputException extends Exception {}
    
    public PageReference SaveCloned() {
       Support_Program__c spNew = this.sp.clone(false,true);
       spNew.RecordTypeId = sp.RecordTypeId;
       insert spNew;
        
       for(ChkEnt ce:chkEntitlements) {
           if (!ce.selected) continue;
           if (ce.e.Name==null) 
           {
               ApexPages.addMessages(new InvalidInputException('Required field Name cannot be blank for any child Entitlements.  Uncheck the box next to any Entitlements you do not wish to clone.'));
               return null;
           }
           Entitlement__c eNew = ce.e.clone(false,false);
           eNew.Support_Program__c = spNew.Id;
           insert eNew;
       }
      
       PageReference viewNewSPPr = new PageReference('/'+spNew.Id);
       viewNewSPPr.setRedirect(true);
       return viewNewSPPr;
    }
    
    static testMethod void testCloneSP() {
        UT_SObjectFactory.InterconnectedSObjectsForNCSP o = new UT_SObjectFactory.InterconnectedSObjectsForNCSP(true,5);
        ApexPages.StandardController sc = new ApexPages.StandardController(o.sp);
        CloneSPCtlEx cx = new CloneSPCtlEx(sc);
        PageReference pr = cx.SaveCloned();
        System.assertEquals(1,[select count() from Entitlement__c where Support_Program__c=:o.sp.Id],'Ctor specified 1 ent.');
        System.assertEquals(false,cx.getZeroEntitlements(),'Ctor specified 5 ents');
    }
    static testMethod void testCloneSP_BlankEntitlementName() {
        UT_SObjectFactory.InterconnectedSObjectsForNCSP o = new UT_SObjectFactory.InterconnectedSObjectsForNCSP(true,5);
        ApexPages.StandardController sc = new ApexPages.StandardController(o.sp);
        CloneSPCtlEx cx = new CloneSPCtlEx(sc);
        cx.chkEntitlements[0].selected = true;
        cx.chkEntitlements[0].e.Name = null;
        PageReference pr = cx.SaveCloned();
        system.assertEquals(null,pr,'Empty name field should fail.');
    }    
}